<template>
  <!-- text-sm/[30px] 表示文字小号，行高为 30px -->
  <div
      class="sticky top-[5.5rem] text-sm/[30px] w-full p-5 mb-3 bg-white border border-gray-200 rounded-lg dark:bg-gray-800 dark:border-gray-700">
    <!-- 目录标题 -->
    <h2 class="flex items-center mb-2 font-bold text-gray-900 uppercase dark:text-white">
      <!-- 目录图标 -->
      <svg t="1699441758495" class="icon w-3.5 h-3.5 mr-2" viewBox="0 0 1024 1024" version="1.1"
           xmlns="http://www.w3.org/2000/svg" p-id="4043" width="200" height="200">
        <path
            d="M857.6 25.6a76.8 76.8 0 0 1 76.8 76.8v819.2a76.8 76.8 0 0 1-76.8 76.8H166.4a76.8 76.8 0 0 1-76.8-76.8V102.4a76.8 76.8 0 0 1 76.8-76.8h691.2z m-102.4 678.4H473.6l-2.2528 0.064a38.4 38.4 0 0 0 0 76.672L473.6 780.8h281.6l2.2528-0.064a38.4 38.4 0 0 0 0-76.672L755.2 704z m0-230.4H473.6l-2.2528 0.064a38.4 38.4 0 0 0 0 76.672L473.6 550.4h281.6l2.2528-0.064a38.4 38.4 0 0 0 0-76.672L755.2 473.6z m0-230.4H473.6l-2.2528 0.064a38.4 38.4 0 0 0 0 76.672L473.6 320h281.6l2.2528-0.064a38.4 38.4 0 0 0 0-76.672L755.2 243.2z"
            fill="#6B57FE" p-id="4044"></path>
        <path
            d="M281.6 691.2a51.2 51.2 0 1 1 0 102.4 51.2 51.2 0 0 1 0-102.4z m0-230.4a51.2 51.2 0 1 1 0 102.4 51.2 51.2 0 0 1 0-102.4z m0-230.4a51.2 51.2 0 1 1 0 102.4 51.2 51.2 0 0 1 0-102.4z"
            fill="#FFBA00" p-id="4045"></path>
      </svg>
      文章目录
    </h2>

    <div class="toc-wrapper" :class="[isDark ? 'dark' : '']">
      <ul class="toc">
        <li v-for="(h1, index) in titles" :key="index">
          <span
              class="py-2 block cursor-pointer hover:text-blue-600 transition-colors pl-5"
              :class="[h1.index == activeHeadingIndex ? 'active py-1 text-sky-600 border-l-2 border-sky-600 font-bold' : 'text-gray-500 font-normal']"
              @click="scrollToView(h1.offsetTop)"
          >
            {{ h1.text }}
          </span>
          <!-- 二级标题 -->
          <ul v-if="h1.children && h1.children.length > 0">
            <li v-for="(h2, index1) in h1.children" :key="index1">
              <span
                  class="py-2 block cursor-pointer hover:text-blue-600 transition-colors pl-10"
                  :class="[h2.index == activeHeadingIndex ? 'active py-1 text-sky-600 border-l-2 border-sky-600 font-bold' : 'text-gray-500 font-normal']"
                  @click="scrollToView(h2.offsetTop)"
              >
                {{ h2.text }}
              </span>
              <!-- 三级标题 -->
              <ul v-if="h2.children && h2.children.length > 0">
                <li v-for="(h3, index2) in h2.children" :key="index2">
                  <span
                      class="py-2 block cursor-pointer hover:text-blue-600 transition-colors pl-15"
                      :class="[h3.index == activeHeadingIndex ? 'active py-1 text-sky-600 border-l-2 border-sky-600 font-bold' : 'text-gray-500 font-normal']"
                      @click="scrollToView(h3.offsetTop)"
                  >
                    {{ h3.text }}
                  </span>
                  <!-- 四级标题 -->
                  <ul v-if="h3.children && h3.children.length > 0">
                    <li v-for="(h4, index3) in h3.children" :key="index3">
                      <span
                          class="py-2 block cursor-pointer hover:text-blue-600 transition-colors pl-20"
                          :class="[h4.index == activeHeadingIndex ? 'active py-1 text-sky-600 border-l-2 border-sky-600 font-bold' : 'text-gray-500 font-normal']"
                          @click="scrollToView(h4.offsetTop)"
                      >
                        {{ h4.text }}
                      </span>
                      <!-- 五级标题 -->
                      <ul v-if="h4.children && h4.children.length > 0">
                        <li v-for="(h5, index4) in h4.children" :key="index4">
                          <span
                              class="py-2 block cursor-pointer hover:text-blue-600 transition-colors pl-25"
                              :class="[h5.index == activeHeadingIndex ? 'active py-1 text-sky-600 border-l-2 border-sky-600 font-bold' : 'text-gray-500 font-normal']"
                              @click="scrollToView(h5.offsetTop)"
                          >
                            {{ h5.text }}
                          </span>
                          <!-- 六级标题 -->
                          <ul v-if="h5.children && h5.children.length > 0">
                            <li v-for="(h6, index5) in h5.children" :key="index5">
                                <span
                                    class="py-2 block cursor-pointer hover:text-blue-600 transition-colors pl-30"
                                    :class="[h6.index == activeHeadingIndex ? 'active py-1 text-sky-600 border-l-2 border-sky-600 font-bold' : 'text-gray-500 font-normal']"
                                    @click="scrollToView(h6.offsetTop)"
                                >
                                  {{ h6.text }}
                                </span>
                            </li>
                          </ul>
                        </li>
                      </ul>
                    </li>
                  </ul>
                </li>
              </ul>
            </li>
          </ul>
        </li>
      </ul>
    </div>

  </div>
</template>

<script setup>
import {ref, onMounted, onBeforeUnmount} from 'vue'
import {useDark} from '@vueuse/core'

const isDark = useDark()
// 响应式的目录数据
const titles = ref([])

// 滚动到指定的位置
function scrollToView(offsetTop) {
  window.scrollTo({top: offsetTop, behavior: "smooth"});
}

onMounted(() => {
  // 通过 .artilce-content 样式来获取父级 div
  const container = document.querySelector('.article-content')

  // 使用 MutationObserver 监视 DOM 的变化
  const observer = new MutationObserver(mutationsList => {
    for (let mutation of mutationsList) {
      if (mutation.type === 'childList') {
        // 先清空目录缓存数据
        titles.value = []
        // 计算目录数据
        initTocData(container)

        // 监听所有图片的加载事件
        const images = container.querySelectorAll('img');
        images.forEach(img => {
          img.addEventListener('load', () => {
            // 图片加载完成后重新计算标题的 offsetTop
            initTocData(container)
          })
        });

        // 添加滚动事件监听
        window.addEventListener('scroll', handleContentScroll);
      }
    }
  })
  // 配置监视子节点的变化
  const config = {childList: true, subtree: true}
  // 开始观察正文 div 的内容变化
  observer.observe(container, config)
})

// 记录当前被选中的标题下标
const activeHeadingIndex = ref(-1)

// 处理滚动事件
// 处理滚动事件
function handleContentScroll() {
  // 当前的滚动位置
  let scrollY = window.scrollY
  let maxIndex = -1

  // 递归遍历所有标题
  function traverseTitles(titlesArray) {
    titlesArray.forEach(title => {
      // 获取每个标题的 offset
      let offsetTop = title.offsetTop - 95
      // 如果当前位置大于等于标题位置，则更新最大索引
      if (scrollY >= offsetTop) {
        maxIndex = Math.max(maxIndex, title.index)
      }

      // 递归处理子标题
      if (title.children && title.children.length > 0) {
        traverseTitles(title.children)
      }
    })
  }

  // 开始遍历
  traverseTitles(titles.value)

  // 更新激活的标题索引
  if (activeHeadingIndex.value !== maxIndex) {
  }
  activeHeadingIndex.value = maxIndex
}


// 初始化标题数据
function initTocData(container) {
  // 支持所有标题级别 h1-h5
  let levels = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
  let headings = container.querySelectorAll(levels.join(', '));
  // 存放组装后的目录标题数据
  let titlesArr = [];
  // 用于跟踪各级标题的栈结构
  let headingStack = [];
  // 下标
  let index = 1;

  headings.forEach(heading => {
    // 标题等级
    let headingLevel = parseInt(heading.tagName.substring(1));
    // 标题文字
    let headingText = heading.innerText;
    // 标题的位置（距离顶部的距离）
    let offsetTop = heading.offsetTop - 95

    // 创建新标题项
    let newItem = {
      index,
      level: headingLevel,
      text: headingText,
      offsetTop,
      children: []
    };

    // 维护标题栈结构
    // 移除栈中比当前级别低或等于的标题
    while (headingStack.length > 0 &&
    headingStack[headingStack.length - 1].level >= headingLevel) {
      headingStack.pop();
    }

    // 如果栈为空，说明是顶级标题
    if (headingStack.length === 0) {
      titlesArr.push(newItem);
    } else {
      // 否则作为当前栈顶标题的子级
      headingStack[headingStack.length - 1].children.push(newItem);
    }

    // 将当前标题压入栈
    headingStack.push(newItem);

    // 下标 +1
    index++;
  });
  //设置数据
  titles.value = titlesArr
}

// 移除滚动监听
onBeforeUnmount(() => window.removeEventListener('scroll', handleContentScroll))
</script>

<style scoped>
::v-deep(.toc-wrapper) {
  position: relative;
  overflow-x: hidden;
  overflow-y: auto;
  max-height: 75vh;
  text-overflow: ellipsis;
  white-space: nowrap;
  scroll-behavior: smooth;
}

::v-deep(.toc:before) {
  content: " ";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: -1;
  width: 2px;
  background: #eaecef;
}

::v-deep(.toc li) {
  list-style: none;
}

/* 自定义缩进样式 */
::v-deep(.toc .pl-5) {
  padding-left: 1rem !important;
}

::v-deep(.toc .pl-10) {
  padding-left: 2rem !important;
}

::v-deep(.toc .pl-15) {
  padding-left: 3rem !important;
}

::v-deep(.toc .pl-20) {
  padding-left: 4rem !important;
}

::v-deep(.toc .pl-25) {
  padding-left: 5rem !important;
}

::v-deep(.toc .pl-30) {
  padding-left: 6rem !important;
}

::v-deep(.dark .toc:before) {
  content: " ";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: -1;
  width: 2px;
  background: #30363d;
}

::v-deep(.dark .toc li span) {
  color: #9e9e9e;
}

::v-deep(.dark .toc li .active) {
  color: rgb(2 132 199 / 1);
}

::v-deep(.dark .toc li span:hover) {
  color: rgb(2 132 199 / 1);
}
</style>